///> 系统的文件存储 ,分区处理，循环擦写
#include "file.hpp"
#include "semaphore.hpp"

using namespace device;
using namespace storage;
using namespace systemos;

typedef struct
{
	uint32_t uiAddr;
	uint32_t uiBankSize;
}DiskConfigTPDF;
///> disk cfg
const DiskConfigTPDF mDiskConfig[] = 
{
#ifdef MANUAL_FLASH_ADDR_S1
	{MANUAL_FLASH_ADDR_S1, MANUAL_FLASH_ADDR_R1 >> 1}, ///>地址平分，循环保存
#endif
#ifdef MANUAL_FLASH_ADDR_S2
	{MANUAL_FLASH_ADDR_S2, MANUAL_FLASH_ADDR_R2 >> 1},
#endif
#ifdef MANUAL_FLASH_ADDR_S3
	{MANUAL_FLASH_ADDR_S3, MANUAL_FLASH_ADDR_R3 >> 1},
#endif
#ifdef MANUAL_FLASH_ADDR_S4
	{MANUAL_FLASH_ADDR_S4, MANUAL_FLASH_ADDR_R4 >> 1},
#endif
};

#define FILE_DATA_OFFSET(banksize)	((banksize >> 2) > 2048? 2048: (banksize >> 2))					///<获取扇区文件信息偏移地址
#define FILE_DISK_COUNT							(sizeof(mDiskConfig) / sizeof(DiskConfigTPDF))					///<获取盘数量
#define FILE_RECORD_DATA_OFFSET			(sizeof(RecordInitPackTPDF) + sizeof(SectorInforTPDF))	///<获取扇区记录数据偏移地址

flash* file::mFlash;										///<存储器
static systemos::semaphore *mSemaphore;	///<互斥量

/** 
* @brief      	获取盘可用的扇区 主要是通过硬件盘的标志位和计数来表示可用扇区
* @param[in]  	tDisk   		盘
* @param[in]  	tType   		盘类型
* @retval     	扇区地址
*/
int32_t file::GetUseableAddr(file::DiskTPDF tDisk, DiskTypeTPDF tType)
{
	SectorInforTPDF sector1, sector2;
	DiskConfigTPDF* tdiskptr = (DiskConfigTPDF*)&mDiskConfig[tDisk];
	
	mFlash->Read(tdiskptr->uiAddr, (uint8_t *)&sector1, sizeof(SectorInforTPDF));
	mFlash->Read(tdiskptr->uiAddr + tdiskptr->uiBankSize, (uint8_t *)&sector2, sizeof(SectorInforTPDF));
	switch(tType)
	{
		case DISK_TYPE_ALL:
			if(sector1.Flag == DISK_TYPE_FILE || sector1.Flag == DISK_TYPE_RECORD)
			{
				if(sector2.Flag == DISK_TYPE_FILE || sector2.Flag == DISK_TYPE_RECORD)
				{
					if(sector2.Counter > sector1.Counter)
					{
						return(tdiskptr->uiAddr + tdiskptr->uiBankSize);
					}
					else
					{
						return(tdiskptr->uiAddr);
					}
				}
				else
				{
					return(tdiskptr->uiAddr);
				}
			}
			else if(sector2.Flag == DISK_TYPE_FILE || sector2.Flag == DISK_TYPE_RECORD)
			{
				return(tdiskptr->uiAddr + tdiskptr->uiBankSize);
			}
			else
			{
				return(tdiskptr->uiAddr);
			}
		case DISK_TYPE_FILE:
			if(sector1.Flag == DISK_TYPE_FILE)
			{
				if(sector2.Flag == DISK_TYPE_FILE)
				{
					if(sector2.Counter > sector1.Counter)
					{
						return(tdiskptr->uiAddr + tdiskptr->uiBankSize);
					}
					else
					{
						return(tdiskptr->uiAddr);
					}
				}
				else
				{
					return(tdiskptr->uiAddr);
				}
			}
			else if(sector2.Flag == DISK_TYPE_FILE)
			{
				return(tdiskptr->uiAddr + tdiskptr->uiBankSize);
			}
			else if(sector1.Flag == DISK_TYPE_RECORD || sector2.Flag == DISK_TYPE_RECORD)
			{
				return(-1);
			}
			else
			{
				return(tdiskptr->uiAddr);
			}
		case DISK_TYPE_RECORD:
			if(sector1.Flag == DISK_TYPE_RECORD)
			{
				if(sector2.Flag == DISK_TYPE_RECORD)
				{
					if(sector2.Counter > sector1.Counter)
					{
						return(tdiskptr->uiAddr + tdiskptr->uiBankSize);
					}
					else
					{
						return(tdiskptr->uiAddr);
					}
				}
				else
				{
					return(tdiskptr->uiAddr);
				}
			}
			else if(sector2.Flag == DISK_TYPE_RECORD)
			{
				return(tdiskptr->uiAddr + tdiskptr->uiBankSize);
			}
			else if(sector1.Flag == DISK_TYPE_FILE || sector2.Flag == DISK_TYPE_FILE)
			{
				return(-1);
			}
			else
			{
				return(tdiskptr->uiAddr);
			}
	}
	return(-1);
}

/** 
* @brief      	获取扇区计数值
* @param[in]  	uiAddr   		扇区地址
* @retval     	计数值
*/
uint32_t file::GetCounter(uint32_t uiAddr)
{
	SectorInforTPDF sector1;
	
	mFlash->Read(uiAddr, (uint8_t *)&sector1, sizeof(SectorInforTPDF));
	if(sector1.Flag == FILE_FLAG_NORMALFILE || sector1.Flag == DISK_TYPE_RECORD)
	{
		return(sector1.Counter);
	}
	return(0);
}

/** 
* @brief      	获取扇区对应的无用扇区(对立的扇区)
* @param[in]  	tDisk   		盘
* @param[in]  	uiAddr   		扇区地址
* @retval     	扇区地址
*/
uint32_t file::GetUseLessAddr(file::DiskTPDF tDisk, uint32_t uiAddr)
{
	if(mDiskConfig[tDisk].uiAddr == uiAddr)
	{
		return(uiAddr + mDiskConfig[tDisk].uiBankSize);
	}
	return(uiAddr - mDiskConfig[tDisk].uiBankSize);
}

/** 
* @brief      	擦除扇区
* @param[in]  	tDisk   		盘
* @param[in]  	uiAddr   		扇区地址
* @retval     	None
*/
void file::EraseBank(file::DiskTPDF tDisk, uint32_t uiAddr)
{
	uint32_t i;
	uint8_t blankvalue = mFlash->BlankValue();
	uint8_t ucBuff[32] = {0};
	uint32_t uiSectorSize = mFlash->GetSectorSize();
	DiskConfigTPDF* tdiskptr = (DiskConfigTPDF*)&mDiskConfig[tDisk];
	
	mFlash->Read(uiAddr, (uint8_t *)&ucBuff[0], 8);
	mFlash->Read(uiAddr + sizeof(SectorInforTPDF), (uint8_t *)&ucBuff[8], 8);
	mFlash->Read(uiAddr + FILE_DATA_OFFSET(mDiskConfig[tDisk].uiBankSize), (uint8_t *)&ucBuff[16], 8);
	mFlash->Read(uiAddr + mDiskConfig[tDisk].uiBankSize - 8, (uint8_t *)&ucBuff[24], 8);
	for(i = 0; i < 32; i++)
	{
		if(ucBuff[i] != blankvalue)
		{
			break;
		}
	}
	if(i == 32)
	{
		return;
	}
	for(i = 0; i < tdiskptr->uiBankSize; i += uiSectorSize)
	{
		mFlash->Erase(uiAddr + i);
	}
}

/** 
* @brief      	查找文件
* @param[in]  	uiAddr   		扇区地址
* @param[in]  	cName   		文件名
* @param[in]  	tFileInfor 	文件信息
* @param[in]  	bLast   		是否查找最后一份文件
* @retval     	文件句柄
*/
int32_t file::FileFind(uint32_t uiAddr, const char* cName, FileInforTPDF *tFileInfor, bool bLast)
{
	uint32_t uiStartAddr, i;
	uint8_t namelen, namelen2;
	
	if(mFlash == 0)
	{
		return(-1);
	}
	namelen = strlen(cName);
	uiStartAddr = uiAddr + sizeof(SectorInforTPDF);	///<文件信息起始地址
	for(i = 0; i < 0xff; i++)
	{
		mFlash->Read(uiStartAddr + i * sizeof(FileInforTPDF), (uint8_t *)tFileInfor, sizeof(FileInforTPDF));
		if(tFileInfor->Flag != FILE_FLAG_NORMALFILE)
		{
			if(bLast)
			{
				if(i)
				{
					i--;
				}
				mFlash->Read(uiStartAddr + i * sizeof(FileInforTPDF), (uint8_t *)tFileInfor, sizeof(FileInforTPDF));
				return(i * sizeof(FileInforTPDF) + uiStartAddr);
			}
			break;
		}
		if(tFileInfor->Handle == 0)
		{
			continue;
		}
		namelen2 = strlen(tFileInfor->Name);
		if(memcmp(cName, tFileInfor->Name, namelen > namelen2? namelen:namelen2) == 0)
		{
			return(i * sizeof(FileInforTPDF) + uiStartAddr);
		}
	}
	return(-1);
}

/** 
* @brief      	将文件拷贝至对立扇区
* @param[in]  	tDisk   					盘
* @param[in]  	uiOldAddr   			旧扇区地址
* @param[in]  	uiNewAddr   			新扇区地址
* @param[in]  	cExceptFileName   迁移过程中需要更新的文件名
* @param[in]  	ucExceptFileData  更新的文件数据
* @param[in]  	usExceptFileLen		更新的文件长度
* @retval     	操作结果(文件写满会返回false)
*/
bool file::FileMoveSector(DiskTPDF tDisk, uint32_t uiOldAddr, uint32_t uiNewAddr, const char* cExceptFileName, uint8_t *ucExceptFileData, uint16_t usExceptFileLen)
{
	uint8_t buff[FILE_RW_BUFF_LEN];						///<缓存
	uint32_t uiAddrCount, uiChecksum, i, j;
	FileInforTPDF tFileInfor;									///<文件信息
	SectorInforTPDF tSectorInfor;							///<扇区信息
	tSectorInfor.Flag = FILE_FLAG_NORMALFILE;	///<文件标记
	uint8_t ucNamelen;												///<文件实际文件名长度
	uint32_t uiActlen;												///<文件实际占用长度
	uint32_t uiOldHandle;											///<文件旧句柄
	bool bFiledeleted = false;								///<是否删除文件
	bool bRet = true;
	
	/** 计算文件校验和*/
	ucNamelen = strlen(cExceptFileName);
	uiChecksum = 0;
	for(i = 0; i < usExceptFileLen; i++)
	{
		uiChecksum += ucExceptFileData[i];
	}
	if(ucNamelen > FILE_NAME_LEN)
	{
		ucNamelen = FILE_NAME_LEN;
	}
	memset(buff, 0xff - mFlash->BlankValue(), 8);
	mFlash->Write(uiNewAddr + mDiskConfig[tDisk].uiBankSize - 8, buff, 8);			///<扇区最后8字节写入标记
	uiAddrCount = uiNewAddr + FILE_DATA_OFFSET(mDiskConfig[tDisk].uiBankSize);	///<文件数据起始地址
	tSectorInfor.Counter = GetCounter(uiOldAddr);	///<获取旧扇区计数值
	for(i = 0; i < 0xff; i++)
	{
		mFlash->Read(uiOldAddr + sizeof(SectorInforTPDF) + i * sizeof(FileInforTPDF), (uint8_t *)&tFileInfor, sizeof(FileInforTPDF));///<读取旧扇区文件信息
		if(tFileInfor.Flag != FILE_FLAG_NORMALFILE)	///<文件读取完毕
		{
			break;
		}
		if(tFileInfor.Handle == 0)
		{
			continue;
		}
		if(memcmp(cExceptFileName, tFileInfor.Name, ucNamelen) != 0)	///<其他文件
		{
			uiActlen = tFileInfor.FileLen;
			if(uiActlen & 3)
			{
				uiActlen = (uiActlen & 0xfffffffc) + 4;
			}
			if((uiAddrCount + uiActlen) > (uiNewAddr + mDiskConfig[tDisk].uiBankSize - 8))	///<扇区已满
			{
				return(false);
			}
			uiOldHandle = tFileInfor.Handle;
			tFileInfor.Handle = uiAddrCount;
			/** 写文件信息*/
			if(bFiledeleted)
			{
				mFlash->Write(uiNewAddr + sizeof(SectorInforTPDF) + (i - 1) * sizeof(FileInforTPDF), (uint8_t *)&tFileInfor, sizeof(FileInforTPDF));
			}
			else
			{
				mFlash->Write(uiNewAddr + sizeof(SectorInforTPDF) + i * sizeof(FileInforTPDF), (uint8_t *)&tFileInfor, sizeof(FileInforTPDF));
			}
			/** 写文件数据*/
			for(j = 0; j < uiActlen;)
			{
				if((uiActlen - j) < FILE_RW_BUFF_LEN)
				{
					mFlash->Read(uiOldHandle + j, buff, uiActlen - j);
					mFlash->Write(uiAddrCount + j, buff, uiActlen - j);
					j = uiActlen;
				}
				else
				{
					mFlash->Read(uiOldHandle + j, buff, FILE_RW_BUFF_LEN);
					mFlash->Write(uiAddrCount + j, buff, FILE_RW_BUFF_LEN);
					j += FILE_RW_BUFF_LEN;
				}
			}
			uiAddrCount += uiActlen;
		}
		else		///<本文件
		{
			if(!usExceptFileLen)
			{
				bFiledeleted = true;
				continue;
			}
			uiActlen = usExceptFileLen;
			if(uiActlen & 3)
			{
				uiActlen = (uiActlen & 0xfffffffc) + 4;
			}
			if((uiAddrCount + uiActlen) > (uiNewAddr + mDiskConfig[tDisk].uiBankSize - 8))	///<扇区已满
			{
				bFiledeleted = true;
				bRet = false;
				continue;
			}
			tFileInfor.Handle = uiAddrCount;
			tFileInfor.FileLen = usExceptFileLen;
			tFileInfor.CheckSum = uiChecksum;
			/** 写文件信息*/
			mFlash->Write(uiNewAddr + sizeof(SectorInforTPDF) + i * sizeof(FileInforTPDF), (uint8_t *)&tFileInfor, sizeof(FileInforTPDF));
			/** 写文件数据*/
			for(j = 0; j < uiActlen;)
			{
				if((uiActlen - j) < FILE_RW_BUFF_LEN)
				{
					memset(buff, 0, FILE_RW_BUFF_LEN);
					memcpy(buff, ucExceptFileData + j, usExceptFileLen - j);
					mFlash->Write(uiAddrCount + j, buff, uiActlen - j);
					j = uiActlen;
				}
				else
				{
					mFlash->Write(uiAddrCount + j, ucExceptFileData + j, FILE_RW_BUFF_LEN);
					j += FILE_RW_BUFF_LEN;
				}
			}
			uiAddrCount += uiActlen;
		}
	}
	tSectorInfor.Counter++;	///<扇区计数值累加
	mFlash->Write(uiNewAddr, (uint8_t *)&tSectorInfor, sizeof(SectorInforTPDF));///<写扇区信息
	EraseBank(tDisk, uiOldAddr);///<擦除旧扇区
	return(bRet);
}

/** 
* @brief      	将记录拷贝至对立扇区
* @param[in]  	tDisk   						盘
* @param[in]  	uiOldAddr   				旧扇区地址
* @param[in]  	uiNewAddr   				新扇区地址
* @param[in]  	tRecordInitPack   	记录初始化信息
* @param[in]  	ucExceptRecordData  新记录
* @param[in]  	uiLasetRecordIndex	最后一次记录
* @retval     	操作结果(文件写满会返回false)
*/
bool file::RecordMoveSector(DiskTPDF tDisk, uint32_t uiOldAddr, uint32_t uiNewAddr, RecordInitPackTPDF *tRecordInitPack, uint8_t *ucExceptRecordData, uint32_t uiLasetRecordIndex)
{
	uint8_t ucBuff[FILE_RW_BUFF_LEN];						///<缓存
	RecordHeadTPDF tRecordHead;
	SectorInforTPDF tSectorInfor;
	uint32_t i, j, k, l, uiOldDataAddr, uiNewDataAddr, uiRealItemSize, uiOneLength, uiChecksum;
	
	if(uiLasetRecordIndex == 0)
	{
		return(false);
	}
	if(uiLasetRecordIndex < tRecordInitPack->tRecordInit.usItemLength)
	{
		return(false);
	}
	uiLasetRecordIndex -= 1;
	uiRealItemSize = tRecordInitPack->tRecordInit.usItemSize;
	/** 记录实际占用长度*/
	if(uiRealItemSize & 0x03)
	{
		uiRealItemSize = (uiRealItemSize & 0xfffffffc) + 4;
	}
	uiOneLength = uiRealItemSize + sizeof(RecordHeadTPDF);	///<单条记录实际占用长度
	uiOldDataAddr = uiOldAddr + FILE_RECORD_DATA_OFFSET;
	uiNewDataAddr = uiNewAddr + FILE_RECORD_DATA_OFFSET;
	mFlash->Read(uiOldDataAddr + (uiLasetRecordIndex * uiOneLength), (uint8_t *)&tRecordHead, sizeof(RecordHeadTPDF));
	uiOldDataAddr = uiOldAddr + FILE_RECORD_DATA_OFFSET + (uiLasetRecordIndex - tRecordInitPack->tRecordInit.usItemLength + 2) * uiOneLength;
	/** 最后的记录无效，内部错误*/
	if(tRecordHead.uiFlag != DISK_TYPE_RECORD)
	{
		return(false);
	}
	memset(ucBuff, mFlash->BlankValue() == 0xff?0:0xff, 8);
	mFlash->Write(uiNewAddr + mDiskConfig[tDisk].uiBankSize - 8, ucBuff, 8);			///<扇区最后8字节写入标记
	/** 迁移旧记录*/
	for(i = 0; i < tRecordInitPack->tRecordInit.usItemLength - 1; i++)
	{
		/** 迁移旧记录头*/
		mFlash->Read(uiOldDataAddr + (i * uiOneLength), (uint8_t *)&tRecordHead, sizeof(RecordHeadTPDF));
		tRecordHead.uiOffset = mFlash->BlankValue() == 0xff? 0xffffffff:0;
		mFlash->Write(uiNewDataAddr + (i * uiOneLength), (uint8_t *)&tRecordHead, sizeof(RecordHeadTPDF));
		/** 迁移旧记录数据*/
		for(j = 0; j < uiOneLength;)
		{
			if((uiOneLength - j) < FILE_RW_BUFF_LEN)
			{
				mFlash->Read(uiOldDataAddr + (i * uiOneLength) + sizeof(RecordHeadTPDF) + j, ucBuff, uiOneLength - j);
				mFlash->Write(uiNewDataAddr + (i * uiOneLength) + sizeof(RecordHeadTPDF) + j, ucBuff, uiOneLength - j);
				j = uiOneLength;
			}
			else
			{
				mFlash->Read(uiOldDataAddr + (i * uiOneLength) + sizeof(RecordHeadTPDF) + j, ucBuff, FILE_RW_BUFF_LEN);
				mFlash->Write(uiNewDataAddr + (i * uiOneLength) + sizeof(RecordHeadTPDF) + j, ucBuff, FILE_RW_BUFF_LEN);
				j += FILE_RW_BUFF_LEN;
			}
		}
	}
	uiChecksum = 0;
	/** 计算校验和*/
	for(j = 0; j < tRecordInitPack->tRecordInit.usItemSize; j++)
	{
		uiChecksum += ucExceptRecordData[j];
	}
	/**写新记录*/
	tRecordHead.uiOffset = mFlash->BlankValue() == 0xff?0xffffffff:0;
	tRecordHead.uiCheckSum = uiChecksum;
	tRecordHead.uiFlag = DISK_TYPE_RECORD;
	mFlash->Write(uiNewDataAddr + (i * uiOneLength), (uint8_t *)&tRecordHead, sizeof(RecordHeadTPDF));
	mFlash->Write(uiNewDataAddr + (i * uiOneLength) + sizeof(RecordHeadTPDF), ucExceptRecordData, uiRealItemSize);
	/** 记录偏移量*/
	j = i >> 3;
	i = j % 32;
	j >>= 5;
	for(l = 0; l < j; l++)
	{
		k = mFlash->BlankValue() == 0xff? 0:0xffffffff;
		mFlash->Write(uiNewDataAddr + ((l * 256) * uiOneLength), (uint8_t *)&k, 4);
	}
	if(i)
	{
		k = (1 << i) - 1;
		k = mFlash->BlankValue() == 0xff?(0xffffffff - k):k;
		mFlash->Write(uiNewDataAddr + ((l * 256) * uiOneLength), (uint8_t *)&k, 4);
	}
	/** 写记录初始化信息*/
	mFlash->Write(uiNewAddr + sizeof(SectorInforTPDF), (uint8_t *)tRecordInitPack, sizeof(RecordInitPackTPDF));
	/** 写扇区信息*/
	tSectorInfor.Counter = GetCounter(uiOldAddr) + 1;
	tSectorInfor.Flag = DISK_TYPE_RECORD;
	mFlash->Write(uiNewAddr, (uint8_t *)&tSectorInfor, sizeof(SectorInforTPDF));
	/** 擦除旧扇区*/
	EraseBank(tDisk, uiOldAddr);
	return(true);
}

/** 
* @brief      	查找最后一次记录
* @param[in]  	tDisk   					盘
* @param[in]  	uiAddr   					扇区地址
* @param[in]  	tRecordInitPack   记录初始化信息
* @param[in]  	uiMaxRecord   		最大记录数量
* @retval     	记录索引号
*/
int32_t file::RecordFindLast(DiskTPDF tDisk, uint32_t uiAddr, RecordInitPackTPDF *tRecordInitPack, uint32_t uiMaxRecord)
{
	int32_t i;
	uint32_t j, k, uiOffset, uiRealItemSize;
	RecordHeadTPDF tRecordHead;
	/** 记录实际占用长度*/
	uiRealItemSize = tRecordInitPack->tRecordInit.usItemSize;
	if(uiRealItemSize & 0x03)
	{
		uiRealItemSize = (uiRealItemSize & 0xfffffffc) + 4;
	}
	/** 查找最后一次记录*/
	for(i = 0; i < uiMaxRecord;)
	{
		j = i * (sizeof(RecordHeadTPDF) + uiRealItemSize);
		mFlash->Read(uiAddr + FILE_RECORD_DATA_OFFSET + j, (uint8_t *)&tRecordHead, sizeof(RecordHeadTPDF));
		if(tRecordHead.uiFlag != DISK_TYPE_RECORD)
		{
			break;
		}
		/** 计算后续记录偏移量*/
		k = tRecordHead.uiOffset;
		if(mFlash->BlankValue() == 0xff)
		{
			k = 0xffffffff - k;
		}
		for(uiOffset = 0; uiOffset < 32; uiOffset++)
		{
			if(!(k & 1))
			{
				break;
			}
			k >>= 1;
		}
		if(uiOffset)
		{
			i += uiOffset * 8;
		}
		else
		{
			i++;
		}
	}
	return(i);
}
/** 
* @brief      	文件读取
* @param[in]   	tDisk	文件盘
* @param[in]   	cName	文件名
* @param[in]   	ucData	数据
* @param[in]   	usLen	数据长度
* @retval    	 	操作结果
*/
bool file::Read(DiskTPDF tDisk, const char* cName, uint8_t *ucData, uint16_t usLen)
{
	uint8_t buff[FILE_RW_BUFF_LEN];
	uint32_t i,j,k,l;
	FileInforTPDF tFileInfor;
	int32_t fileinforhandle;
	int32_t iAddr;
	
	if(mFlash == 0)
	{
		return(false);
	}
	if(strlen(cName) > FILE_NAME_LEN - 2)
	{
		return(false);
	}
	mSemaphore->Take(portMAX_DELAY);
	iAddr = GetUseableAddr(tDisk, DISK_TYPE_FILE);
	if(iAddr == -1)
	{
		mSemaphore->Give();
		return(false);
	}
	fileinforhandle = FileFind(iAddr, cName, &tFileInfor, false); ///找到文件句柄
	if(fileinforhandle == -1)
	{
		mSemaphore->Give();
		return(false);
	}
	j = 0;
	for(i = 0; i < tFileInfor.FileLen;)
	{
		k = tFileInfor.FileLen - i;
		if(k > FILE_RW_BUFF_LEN)
		{
			mFlash->Read(tFileInfor.Handle + i, buff, FILE_RW_BUFF_LEN);
			for(l = 0; l < FILE_RW_BUFF_LEN; l++)
			{
				j += buff[l];
			}
			if(usLen > i)
			{
				memcpy(ucData + i, buff, (usLen - i) > FILE_RW_BUFF_LEN? FILE_RW_BUFF_LEN:(usLen - i));
			}
			i += FILE_RW_BUFF_LEN;
		}
		else
		{
			mFlash->Read(tFileInfor.Handle + i, buff, k);
			for(l = 0; l < k; l++)
			{
				j += buff[l];
			}
			if(usLen > i)
			{
				memcpy(ucData + i, buff, (usLen - i) > FILE_RW_BUFF_LEN? FILE_RW_BUFF_LEN:(usLen - i));
			}
			i += k;
		}
	}
	if(j != tFileInfor.CheckSum)
	{
		mSemaphore->Give();
		return(false);
	}
	mSemaphore->Give();
	return(true);
}

/** 
* @brief      	写文件
* @param[in]   	tDisk	文件盘
* @param[in]   	cName	文件名
* @param[in]   	ucData	数据
* @param[in]   	usLen	数据长度
* @retval    	 	操作结果
*/
bool file::Write(DiskTPDF tDisk, const char* cName, uint8_t *ucData, uint16_t usLen)
{
	uint8_t buff[FILE_RW_BUFF_LEN];
	FileInforTPDF tFileInfor;
	FileInforTPDF tNewFile = {0};
	SectorInforTPDF tSectorInfor;
	int32_t iFileinforhandle;
	uint32_t uiChecksum, i, j;
	int32_t iAddr; 
	
	if(mFlash == 0)
	{
		return(false);
	}
	if(strlen(cName) > FILE_NAME_LEN - 2)
	{
		return(false);
	}
	mSemaphore->Take(portMAX_DELAY);
	iAddr = GetUseableAddr(tDisk, DISK_TYPE_FILE);
	if(iAddr == -1)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 计算文件校验和*/
	uiChecksum = 0;
	for(i = 0; i < usLen; i++)
	{
		uiChecksum += ucData[i];
	}
	/** 文件信息初始化*/
	memcpy(tNewFile.Name, cName, strlen(cName));
	tNewFile.CheckSum = uiChecksum;
	tNewFile.FileLen = usLen;
	tNewFile.Flag = FILE_FLAG_NORMALFILE;
	iFileinforhandle = FileFind(iAddr, cName, &tFileInfor, false);		///<查找是否存在文件
	if(iFileinforhandle == -1)	///<文件不存在
	{
		iFileinforhandle = FileFind(iAddr, cName, &tFileInfor, true);	//< 返回最后索引地址
		if(iFileinforhandle != -1)		///<文件可写
		{
			if(tFileInfor.Flag == FILE_FLAG_NORMALFILE)			///<有其他文件
			{
				tNewFile.Handle = tFileInfor.FileLen + tFileInfor.Handle;
				if(tNewFile.Handle & 3)
				{
					tNewFile.Handle = (tNewFile.Handle & 0xfffffffc) + 4;
				}
				iFileinforhandle += sizeof(FileInforTPDF);
			}
			else		///<空盘
			{
				tNewFile.Handle = iFileinforhandle - sizeof(SectorInforTPDF) + FILE_DATA_OFFSET(mDiskConfig[tDisk].uiBankSize);
				memset(buff, 0xff - mFlash->BlankValue(), 8);
				mFlash->Write(iAddr + mDiskConfig[tDisk].uiBankSize - 8, buff, 8);			///<扇区最后8字节写入标记
			}
			if(usLen & 3)
			{
				usLen = (usLen & 0xfffffffc) + 4;
			}
			/** 文件信息区已满*/
			if((iFileinforhandle - iAddr + sizeof(FileInforTPDF)) > FILE_DATA_OFFSET(mDiskConfig[tDisk].uiBankSize))
			{
				return(false);
			}
			/** 扇区空间已满*/
			if((tNewFile.Handle + usLen) > (iAddr + mDiskConfig[tDisk].uiBankSize - 8))
			{
				return(false);
			}
			mFlash->Write(iFileinforhandle, (uint8_t *)&tNewFile, sizeof(FileInforTPDF));			///<写文件信息
			/** 写文件数据*/
			for(j = 0; j < usLen;)
			{
				if((usLen - j) < FILE_RW_BUFF_LEN)
				{
					memset(buff, 0, FILE_RW_BUFF_LEN);
					memcpy(buff, ucData + j, tNewFile.FileLen - j);
					mFlash->Write(tNewFile.Handle + j, buff, usLen - j);
					j = usLen;
				}
				else
				{
					if(tNewFile.FileLen - j < FILE_RW_BUFF_LEN)
					{
						memset(buff, 0, FILE_RW_BUFF_LEN);
						memcpy(buff, ucData + j, tNewFile.FileLen - j);
						mFlash->Write(tNewFile.Handle + j, buff, FILE_RW_BUFF_LEN);
					}
					else
					{
						mFlash->Write(tNewFile.Handle + j, ucData + j, FILE_RW_BUFF_LEN);
					}
					j += FILE_RW_BUFF_LEN;
				}
			}
			/** 盘信息是否为空,否则写盘信息*/
			i = GetUseableAddr(tDisk, DISK_TYPE_FILE);
			mFlash->Read(i, (uint8_t *)&tSectorInfor, sizeof(SectorInforTPDF));
			if(tSectorInfor.Flag != FILE_FLAG_NORMALFILE)
			{
				tSectorInfor.Flag = FILE_FLAG_NORMALFILE;
				tSectorInfor.Counter = 0; ////> 写盘信息
				mFlash->Write(i, (uint8_t *)&tSectorInfor, sizeof(SectorInforTPDF));
			}
		}
		else
		{
			mSemaphore->Give();
			return(false);
		}
	}
	else	///<文件存在,将文件拷贝至新扇区
	{
		if(!FileMoveSector(tDisk, iAddr, GetUseLessAddr(tDisk, iAddr), cName, ucData, usLen))
		{
			mSemaphore->Give();
			return(false);
		}
	}
	mSemaphore->Give();
	return(true);
}

/** 
* @brief      	记录读取
* @param[in]   	tDisk				文件盘
* @param[in]   	usRecordID	记录ID
* @param[in]   	usIndex			索引号(0表示最近一条)
* @param[in]   	ucData			数据
* @param[in]   	usLen				数据长度
* @retval    	 	操作结果
*/
bool file::Read(DiskTPDF tDisk, uint16_t usRecordID, uint16_t usIndex, uint8_t *ucData, uint16_t usLen)
{
	int32_t iAddr;
	SectorInforTPDF tSectorInfor;
	RecordInitPackTPDF tRecordInitPack;
	RecordHeadTPDF tRecordHead;
	uint32_t uiMaxRecord, uiRealItemSize, uiDataAddr, uiChecksum, uiLastRecordIndex, uiOneLength;
	uint32_t i;
	
	if(mFlash == 0)
	{
		return(false);
	}
	mSemaphore->Take(portMAX_DELAY);
	iAddr = GetUseableAddr(tDisk, DISK_TYPE_RECORD);
	/** 该盘非记录属性，属于文件属性*/
	if(iAddr == -1)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 获取盘信息，记录初始化*/
	mFlash->Read(iAddr, (uint8_t *)&tSectorInfor, sizeof(SectorInforTPDF));
	mFlash->Read(iAddr + sizeof(SectorInforTPDF), (uint8_t *)&tRecordInitPack, sizeof(RecordInitPackTPDF));
	/** 盘信息与记录初始化信息错误*/
	if(tSectorInfor.Flag != DISK_TYPE_RECORD || 
		 tRecordInitPack.uiFlag != DISK_TYPE_RECORD || 
	   tRecordInitPack.tRecordInit.usRecordID != usRecordID ||
	   tRecordInitPack.tRecordInit.usItemSize != usLen ||
		 tRecordInitPack.tRecordInit.usItemLength == 0 ||
		 tRecordInitPack.tRecordInit.usItemSize == 0)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 记录实际占用长度*/
	uiRealItemSize = tRecordInitPack.tRecordInit.usItemSize;
	if(uiRealItemSize & 0x03)
	{
		uiRealItemSize = (uiRealItemSize & 0xfffffffc) + 4;
	}
	uiDataAddr = iAddr + FILE_RECORD_DATA_OFFSET;
	uiOneLength = uiRealItemSize + sizeof(RecordHeadTPDF);
	uiMaxRecord = (mDiskConfig[tDisk].uiBankSize - FILE_RECORD_DATA_OFFSET) / uiOneLength;
	if(!uiMaxRecord)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 查找最后一次记录*/
	uiLastRecordIndex = RecordFindLast(tDisk, iAddr, &tRecordInitPack, uiMaxRecord);
	/** 无记录*/
	if(uiLastRecordIndex == 0)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 记录超出索引*/
	if((usIndex + 1) > uiLastRecordIndex)
	{
		mSemaphore->Give();
		return(false);
	}
	uiLastRecordIndex = uiLastRecordIndex - usIndex - 1;
	/** 读取记录头和记录信息*/
	mFlash->Read(uiDataAddr + (uiLastRecordIndex * uiOneLength), (uint8_t *)&tRecordHead, sizeof(RecordHeadTPDF));
	mFlash->Read(uiDataAddr + (uiLastRecordIndex * uiOneLength) + sizeof(RecordHeadTPDF), ucData, tRecordInitPack.tRecordInit.usItemSize);
	uiChecksum = 0;
	for(i = 0; i < tRecordInitPack.tRecordInit.usItemSize; i++)
	{
		uiChecksum += ucData[i];
	}
	mSemaphore->Give();
	if(uiChecksum != tRecordHead.uiCheckSum || tRecordHead.uiFlag != DISK_TYPE_RECORD)
	{
		return(false);
	}
	return(true);
}

/** 
* @brief      	写记录
* @param[in]   	tDisk				文件盘
* @param[in]   	usRecordID	记录ID
* @param[in]   	ucData			数据
* @param[in]   	usLen				数据长度
* @retval    	 	操作结果
*/
bool file::Write(DiskTPDF tDisk, uint16_t usRecordID, uint8_t *ucData, uint16_t usLen)
{
	int32_t iAddr;
	SectorInforTPDF tSectorInfor;
	RecordInitPackTPDF tRecordInitPack;
	RecordHeadTPDF tRecordHead;
	uint32_t uiMaxRecord, uiRealItemSize, uiDataAddr, uiChecksum, uiLastRecordIndex, uiOneLength;
	uint32_t j, k, l, m;
	
	if(mFlash == 0)
	{
		return(false);
	}
	mSemaphore->Take(portMAX_DELAY);
	iAddr = GetUseableAddr(tDisk, DISK_TYPE_RECORD);
	/** 该盘非记录属性，属于文件属性*/
	if(iAddr == -1)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 获取盘信息，记录初始化*/
	mFlash->Read(iAddr, (uint8_t *)&tSectorInfor, sizeof(SectorInforTPDF));
	mFlash->Read(iAddr + sizeof(SectorInforTPDF), (uint8_t *)&tRecordInitPack, sizeof(RecordInitPackTPDF));
	/** 盘信息与记录初始化信息错误*/
	if(tSectorInfor.Flag != DISK_TYPE_RECORD || 
		 tRecordInitPack.uiFlag != DISK_TYPE_RECORD || 
	   tRecordInitPack.tRecordInit.usRecordID != usRecordID ||
	   tRecordInitPack.tRecordInit.usItemSize != usLen ||
		 tRecordInitPack.tRecordInit.usItemLength == 0 ||
		 tRecordInitPack.tRecordInit.usItemSize == 0)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 记录实际占用长度*/
	uiRealItemSize = tRecordInitPack.tRecordInit.usItemSize;
	if(uiRealItemSize & 0x03)
	{
		uiRealItemSize = (uiRealItemSize & 0xfffffffc) + 4;
	}
	uiDataAddr = iAddr + FILE_RECORD_DATA_OFFSET;
	uiOneLength = uiRealItemSize + sizeof(RecordHeadTPDF);
	uiMaxRecord = (mDiskConfig[tDisk].uiBankSize - FILE_RECORD_DATA_OFFSET) / uiOneLength;
	if(!uiMaxRecord)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 查找最后一次记录*/
	uiLastRecordIndex = RecordFindLast(tDisk, iAddr, &tRecordInitPack, uiMaxRecord);
	/** 记录已满*/
	if((uiLastRecordIndex + 1) >= uiMaxRecord)
	{
		if(!RecordMoveSector(tDisk, iAddr, GetUseLessAddr(tDisk, iAddr), &tRecordInitPack, ucData, uiLastRecordIndex))
		{
			mSemaphore->Give();
			return(false);
		}
	}
	else
	{
		uiChecksum = 0;
		/** 计算校验和*/
		for(j = 0; j < usLen; j++)
		{
			uiChecksum += ucData[j];
		}
		tRecordHead.uiOffset = mFlash->BlankValue() == 0xff?0xffffffff:0;
		tRecordHead.uiCheckSum = uiChecksum;
		tRecordHead.uiFlag = DISK_TYPE_RECORD;
		/** 写记录头*/
		mFlash->Write(uiDataAddr + (uiLastRecordIndex * uiOneLength), (uint8_t *)&tRecordHead, sizeof(RecordHeadTPDF));
		if(usLen & 0x03)
		{
			usLen = (usLen & 0xfffffffc) + 4;
		}
		/** 写记录数据*/
		mFlash->Write(uiDataAddr + (uiLastRecordIndex * uiOneLength) + sizeof(RecordHeadTPDF), ucData, usLen);
		/** 记录偏移量*/
		j = uiLastRecordIndex >> 3;
		k = j % 32;
		j >>= 5;
		for(l = 0; l < j; l++)
		{
			m = mFlash->BlankValue() == 0xff? 0:0xffffffff;
			mFlash->Write(uiDataAddr + ((l * 256) * uiOneLength), (uint8_t *)&m, 4);
		}
		if(k)
		{
			m = (1 << k) - 1;
			m = mFlash->BlankValue() == 0xff?(0xffffffff - m):m;
			mFlash->Write(uiDataAddr + ((l * 256) * uiOneLength), (uint8_t *)&m, 4);
		}
	}
	mSemaphore->Give();
	return(true);
}

/** 
* @brief      	删除文件
* @param[in]   	tDisk	文件盘
* @param[in]   	cName	文件名
* @retval    	 	操作结果
*/
bool file::Delete(DiskTPDF tDisk, const char* cName)
{
	FileInforTPDF tFileInfor;
	int32_t fileinforhandle;
	int32_t iAddr;
	
	if(mFlash == 0)
	{
		return(false);
	}
	if(strlen(cName) > FILE_NAME_LEN - 2)
	{
		return(false);
	}
	mSemaphore->Take(portMAX_DELAY);
	iAddr = GetUseableAddr(tDisk, DISK_TYPE_FILE);
	if(iAddr == -1)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 文件信息初始化*/
	fileinforhandle = FileFind(iAddr, cName, &tFileInfor, false);		///<查找是否存在文件
	if(fileinforhandle == -1)	///<文件不存在
	{
		mSemaphore->Give();
		return(false);
	}
	else	///<文件存在,将文件拷贝至新扇区
	{
		if(!FileMoveSector(tDisk, iAddr, GetUseLessAddr(tDisk, iAddr), cName, 0, 0))
		{
			mSemaphore->Give();
			return(false);
		}
	}
	mSemaphore->Give();
	return(true);
}

/** 
* @brief      	格式化盘
* @param[in]   	tDisk	文件盘
* @retval    	 	操作结果
*/
bool file::Format(DiskTPDF tDisk)
{
	uint32_t i;
	uint32_t uiSectorSize = mFlash->GetSectorSize();
	DiskConfigTPDF* tdiskptr = (DiskConfigTPDF*)&mDiskConfig[tDisk];
	
	if(mFlash == 0)
	{
		return(false);
	}
	mSemaphore->Take(portMAX_DELAY);
	for(i = 0; i < tdiskptr->uiBankSize * 2; i += uiSectorSize)
	{
		if(!mFlash->Erase(tdiskptr->uiAddr + i))
		{
			mSemaphore->Give();
			return(false);
		}
	}
	mSemaphore->Give();
	return(true);
}

/** 
* @brief      	文件初始化
* @param[in]   	tFls	存储器
* @retval    	 	None
*/
void file::Init(flash *tFls)
{
	uint8_t i;
	uint32_t uiAddr;
	SectorInforTPDF sector1;
	
	mFlash = tFls;
	if(mFlash == 0)
	{
		return;
	}
	mSemaphore = new systemos::semaphore();
	mSemaphore->Take(portMAX_DELAY);
	for(i = 0; i < FILE_DISK_COUNT; i++)
	{
		uiAddr = GetUseableAddr((DiskTPDF)i, DISK_TYPE_ALL);
		EraseBank((DiskTPDF)i, GetUseLessAddr((DiskTPDF)i, uiAddr));
		mFlash->Read(uiAddr, (uint8_t *)&sector1, sizeof(SectorInforTPDF));
		if(sector1.Flag != DISK_TYPE_FILE)
		{
			if(sector1.Flag != DISK_TYPE_RECORD)
			{
				EraseBank((DiskTPDF)i, uiAddr);
			}
		}
	}
	mSemaphore->Give();
}

/** 
* @brief      	记录初始化
* @param[in]   	tDisk	文件盘
* @param[in]   	tRecordInit	记录初始化
* @retval    	 	None
*/
bool file::RecordInit(DiskTPDF tDisk, RecordInitTPDF *tRecordInit)
{
	int32_t iAddr;
	uint8_t buff[8];						///<缓存
	SectorInforTPDF tSectorInfor;
	RecordInitPackTPDF tRecordInitPack;
	uint32_t uiRealItemSize;
	
	if(mFlash == 0 || tRecordInit->usItemLength == 0 || tRecordInit->usItemSize == 0)
	{
		return(false);
	}
	mSemaphore->Take(portMAX_DELAY);
	iAddr = GetUseableAddr(tDisk, DISK_TYPE_RECORD);
	/** 该盘非记录属性，属于文件属性*/
	if(iAddr == -1)
	{
		mSemaphore->Give();
		return(false);
	}
	/** 获取盘信息，记录初始化*/
	mFlash->Read(iAddr, (uint8_t *)&tSectorInfor, sizeof(SectorInforTPDF));
	mFlash->Read(iAddr + sizeof(SectorInforTPDF), (uint8_t *)&tRecordInitPack, sizeof(RecordInitPackTPDF));
	if(tSectorInfor.Flag == DISK_TYPE_RECORD)
	{
		if(tRecordInitPack.uiFlag == DISK_TYPE_RECORD)
		{
			/** 当前盘记录初始化与入口参数不一致*/
			if(tRecordInitPack.tRecordInit.usItemLength != tRecordInit->usItemLength ||
				 tRecordInitPack.tRecordInit.usItemSize != tRecordInit->usItemSize ||
				 tRecordInitPack.tRecordInit.usRecordID != tRecordInit->usRecordID)
			{
				mSemaphore->Give();
				return(false);
			}
			mSemaphore->Give();
			return(true);
		}
		else	///<不存在记录初始化，写记录初始化
		{
			memcpy(&tRecordInitPack.tRecordInit, tRecordInit, sizeof(RecordInitTPDF));
			tRecordInitPack.uiFlag = DISK_TYPE_RECORD;
			mFlash->Write(iAddr + sizeof(SectorInforTPDF), (uint8_t *)&tRecordInitPack, sizeof(RecordInitPackTPDF));
		}
	}
	else		///<空盘
	{
		uiRealItemSize = tRecordInit->usItemSize;
		if(uiRealItemSize & 0x03)
		{
			uiRealItemSize = (uiRealItemSize & 0xfffffffc) + 4;
		}
		/** 盘无法记录最大记录数量*/
		if((sizeof(tSectorInfor) + sizeof(RecordInitPackTPDF) + ((sizeof(RecordHeadTPDF) + uiRealItemSize) * tRecordInit->usItemLength) + 8) > mDiskConfig[tDisk].uiBankSize)
		{
			mSemaphore->Give();
			return(false);
		}
		tSectorInfor.Flag = DISK_TYPE_RECORD;
		tSectorInfor.Counter = 0;
		mFlash->Write(iAddr, (uint8_t *)&tSectorInfor, sizeof(SectorInforTPDF));
		memcpy(&tRecordInitPack.tRecordInit, tRecordInit, sizeof(RecordInitTPDF));
		tRecordInitPack.uiFlag = DISK_TYPE_RECORD;
		mFlash->Write(iAddr + sizeof(SectorInforTPDF), (uint8_t *)&tRecordInitPack, sizeof(RecordInitPackTPDF));
		memset(buff, mFlash->BlankValue() == 0xff?0:0xff, 8);
		mFlash->Write(iAddr + mDiskConfig[tDisk].uiBankSize - 8, buff, 8);			///<扇区最后8字节写入标记
	}
	mSemaphore->Give();
	return(true);
}

